package com.zhz.mutil.application.service;

import com.zhz.mutil.domain.contract.constants.DbDataSourceConstant;
import com.zhz.mutil.domain.contract.dto.DbDataSourceDTO;
import com.zhz.mutil.infras.exception.ServiceException;
import com.zhz.mutil.infras.repository.entity.DbSourceConfig;
import com.zhz.mutil.infras.repository.service.DbSourceConfigService;
import com.zhz.mutil.infras.utils.DbLinkUtil;
import com.zhz.mutil.infras.utils.DbOprUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 数据源业务处理
 *
 * @author zhouhengzhe
 */
@Slf4j
@Service
public class DataSourceBizService {


    @Autowired
    private DbOprUtil dbOprUtil;

    @Autowired
    private DbSourceConfigService dbSourceConfigService;


    /**
     * 获取所有数据源
     */
    public List<DbDataSourceDTO> find() {
        Set<String> st = dbOprUtil.getAllDataSource();
        List<DbDataSourceDTO> list = new ArrayList<>();
        if (st != null && !st.isEmpty()) {
            for (String str : st) {
                DbDataSourceDTO dbDataSourceDTO = new DbDataSourceDTO();
                dbDataSourceDTO.setPoolName(str);
                //数据源连接等信息在这里就不获取了，自己debug去找，里面都有
                list.add(dbDataSourceDTO);
            }
        }
        return list;
    }

    /**
     * 添加数据源
     */
    public void add(DbDataSourceDTO form) {
        //验证数据源是否可用
        checked(form);
        //添加到源中成功后 在添加到数据源库中
        dbSourceConfigService.add(form);

        //如果成功 Add到数据源中
        dbOprUtil.addDataSource(form);
    }

    /**
     * 验证数据源是否可用
     */
    public void checked(DbDataSourceDTO form) {
        //master为系统初始化数据源名称，不能被其他数据源替代和删除
        if (form != null && StringUtils.isNotEmpty(form.getPoolName()) && "master".equalsIgnoreCase(form.getPoolName())) {
            throw new ServiceException("该关键字不能作为名称使用");
        }
        switch (Objects.requireNonNull(form).getType().toLowerCase()) {
            case "mysql":
                form.setDriverClassName(DbDataSourceConstant.MYSQL_HIGH_DRIVER_CLASS_NAME);
                break;
            case "oracle":
                form.setDriverClassName(DbDataSourceConstant.ORACLE_DRIVER_CLASS_NAME);
                break;
            case "postgresql":
                form.setDriverClassName(DbDataSourceConstant.POSTGRESQL_HIGH_DRIVER_CLASS_NAME);
                break;
            default:
                //默认mysql 低版本
                form.setDriverClassName(DbDataSourceConstant.MYSQL_LOW_DRIVER_CLASS_NAME);
        }
        //判断数据源连接是否能够连接成功
        DbLinkUtil.verifyUrlConnStatus(form.getUrl(), form.getDriverClassName(), form.getUsername(), form.getPassword());
    }

    /**
     * 修改数据源
     */
    public void update(DbDataSourceDTO form) {
        //验证数据源是否可用
        checked(form);
        //修改数据源库中存储数据源
        dbSourceConfigService.modify(form);
        //删除已有数据源
        delete(form);

        //如果成功 Add到数据源中
        dbOprUtil.addDataSource(form);
    }

    /**
     * 删除数据源
     */
    public void delete(DbDataSourceDTO form) {
        //删除数据源
        dbSourceConfigService.delete(form);
        if (!form.getPoolName().equals("master")) {
            dbOprUtil.removeByDataSourceByName(form.getPoolName());
        }
    }

    /**
     * 初始化
     */
    @PostConstruct
    public void init() {
        /**
         * 默认添加master
         */
        //todo 代码下来先改这里
        DbDataSourceDTO dbDataSourceDTO = DbDataSourceDTO
                .builder()
                .url("jdbc:mysql://localhost:3308/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC")
                .username("root")
                .password("123456")
                .driverClassName("com.mysql.cj.jdbc.Driver")
                .poolName("master")
                .type("mysql")
                .build();
        //如果成功 Add到数据源中
        dbOprUtil.addDataSource(dbDataSourceDTO);

        dbOprUtil.changeByDataSourceByName("master");
        //查询所有数据源
        List<DbSourceConfig> list = dbSourceConfigService.list();
        log.info("数据源数量：{}", list.size());
        list.stream()
                .map(dbSourceConfig -> DbDataSourceDTO
                        .builder()
                        .url(dbSourceConfig.getUrl())
                        .username(dbSourceConfig.getUsername())
                        .password(dbSourceConfig.getPassword())
                        .driverClassName(dbSourceConfig.getDriverClassName())
                        .poolName(dbSourceConfig.getPoolName())
                        .type(dbSourceConfig.getType())
                        .poolName(dbSourceConfig.getPoolName())
                        .build())
                .collect(Collectors.toList())
                .stream().filter(Objects::nonNull)
                .forEach(item -> {
                    //验证数据源是否可用
                    checked(item);
                    //添加到数据源中
                    dbOprUtil.addDataSource(item);
                });
    }
}